package pl.sar.auth.gui;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Collection;
import java.util.Properties;

import javax.naming.InitialContext;

import org.apache.log4j.Logger;

import pl.sar.auth.server.ejb.beans.IClientService;
import pl.sar.auth.server.ejb.beans.IProjectService;
import pl.sar.auth.server.ejb.entities.User;
import pl.sar.auth.server.ejb.exceptions.UserException;

public class ApplicationClient implements IApplicationClient, UncaughtExceptionHandler
{
    private static Logger logger = Logger.getLogger( ApplicationClient.class );

    private Properties applicationProperties;
    private Properties clientProperties;

    private InitialContext initialContext;

    public ApplicationClient()
    {

    }

    @Override
    public void run()
    {
        logger.info( "Starting application." );

        setupProperties();

        setupConnection();

        shutdown();
    }

    @Override
    public void shutdown()
    {
        logger.info( "Application stopped." );
    }

    private void setupProperties()
    {
        applicationProperties = new Properties();
        try
        {
            clientProperties = new Properties();
            InputStream is = getClass().getResourceAsStream( "/client.properties" );
            clientProperties.load( is );

            applicationProperties.setProperty( "com.sun.corba.ee.transport.ORBWaitForResponseTimeout", "1" );
            applicationProperties.setProperty( "com.sun.corba.ee.transport.ORBTCPConnectTimeouts",
                "100:500:100:500" );
            applicationProperties.setProperty( "com.sun.corba.ee.transport.ORBTCPTimeouts",
                "500:2000:50:1000" );

            applicationProperties.setProperty( "java.naming.factory.initial",
                "com.sun.enterprise.naming.SerialInitContextFactory" );

            applicationProperties.setProperty( "java.naming.factory.url.pkgs", "com.sun.enterprise.naming" );

            applicationProperties.setProperty( "java.naming.factory.state",
                "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl" );

            applicationProperties.setProperty( "org.omg.CORBA.ORBInitialHost",
                clientProperties.getProperty( "serverUrl" ) );

            applicationProperties.setProperty( "org.omg.CORBA.ORBInitialPort",
                clientProperties.getProperty( "serverPort" ) );
        }
        catch( FileNotFoundException e )
        {
            logger.error( "File client.properties not found!" );
        }
        catch( IOException e )
        {
            logger.error( "Fatal IO exception" );
            e.printStackTrace();
        }
        catch( Exception e )
        {
            logger.error( "Fatal exception" );
            e.printStackTrace();
        }

    }

    private void setupConnection()
    {
        try
        {

            initialContext = new InitialContext( applicationProperties );

            int timeout = Integer.parseInt( clientProperties.getProperty( "connectionTimeout" ) );
            logger.debug( "Connection timeout set to: " + timeout );

            TimeoutChecker timeoutChecker = new TimeoutChecker( timeout, this );
            timeoutChecker.start();

            IProjectService projectService =
                (IProjectService)initialContext.lookup( "pl.sar.auth.server.ejb.beans.IProjectService" );

            IClientService clientService =
                (IClientService)initialContext.lookup( "pl.sar.auth.server.ejb.beans.IClientService" );

            timeoutChecker.interrupt();

            testExecute( projectService, clientService );
        }
        catch( Exception ex )
        {
            // logger.error( ex.getMessage(), ex );
        }
    }

    @Override
    public void uncaughtException( Thread t, Throwable e )
    {
        if( e instanceof TimeoutException )
        {
            logger.error( "Connection timeout!" );
            shutdown();
        }
    }

    private void testExecute( IProjectService project, IClientService client )
    {

        try
        {
            logger.info( "Executing test..." );

            String projectName = clientProperties.getProperty( "projectName" );

            Long projectId = project.registerProject( projectName );

            try 
            {
                client.createUser( "figo", "m1", projectId );

                client.createUser( "fago", "m2", projectId );				
			}
            catch (UserException e) 
            {
	        	logger.error( e.getMessage() );
			}

            Collection< User > projectUsers = project.getProjectUsers( projectName );

            logger.info( "Project has [" + projectUsers.size() + "] registered users." );

            logger.info( "Success!" );
        }

        catch( Exception e )
        {
            logger.error( "Some error on server side...", e );
        }
    }
}
